package com.zp.drug.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.base.api.RemoteSerialNumberUtils;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.DateUtils;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.drug.entity.DrugInventoryCheckPreparation;
import com.zp.drug.entity.bo.DrugInventoryCheckPreparationBo;
import com.zp.drug.entity.bo.DrugStockBo;
import com.zp.drug.entity.vo.DrugInventoryCheckPreparationVo;
import com.zp.drug.mapper.DrugInventoryCheckPreparationMapper;
import com.zp.drug.mapper.DrugStockMapper;
import com.zp.drug.service.IDrugInventoryCheckPreparationService;
import com.zp.system.api.entity.SysDictData;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 药品预盘点表Service业务层处理
 *
 * @author zhang peng
 * @ date 2024-06-14
 */
@RequiredArgsConstructor
@Service
public class DrugInventoryCheckPreparationServiceImpl implements IDrugInventoryCheckPreparationService {

    // 规格单位
    static List<SysDictData> SPEC_UNIT_MAP = CacheUtils.get(CacheNames.SYS_DICT, CacheNames.SPEC_UNIT);
    private final DrugInventoryCheckPreparationMapper baseMapper;
    private final DrugStockMapper drugStockMapper;
    @DubboReference
    private RemoteSerialNumberUtils remoteSerialNumberUtils;

    /**
     * 查询药品预盘点表
     */
    @Override
    public DrugInventoryCheckPreparationVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询药品预盘点表列表(分页)
     */
    @Override
    public TableDataInfo<DrugInventoryCheckPreparationVo> queryPageList(DrugInventoryCheckPreparationBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DrugInventoryCheckPreparation> lqw = buildQueryWrapper(bo);
        Page<DrugInventoryCheckPreparationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询药品预盘点表列表(不分页)
     */
    @Override
    public List<DrugInventoryCheckPreparationVo> queryList(DrugInventoryCheckPreparationBo bo) {
        LambdaQueryWrapper<DrugInventoryCheckPreparation> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DrugInventoryCheckPreparation> buildQueryWrapper(DrugInventoryCheckPreparationBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DrugInventoryCheckPreparation> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCheckYearMonth() != null, DrugInventoryCheckPreparation::getCheckYearMonth, bo.getCheckYearMonth());
        lqw.eq(StringUtils.isNotBlank(bo.getInventoryNo()), DrugInventoryCheckPreparation::getInventoryNo, bo.getInventoryNo());
        lqw.eq(StringUtils.isNotBlank(bo.getSaveType()), DrugInventoryCheckPreparation::getSaveType, bo.getSaveType());
        lqw.eq(bo.getItemNo() != null, DrugInventoryCheckPreparation::getItemNo, bo.getItemNo());
        lqw.eq(StringUtils.isNotBlank(bo.getStockId()), DrugInventoryCheckPreparation::getStockId, bo.getStockId());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugCode()), DrugInventoryCheckPreparation::getDrugCode, bo.getDrugCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugClass()), DrugInventoryCheckPreparation::getDrugClass, bo.getDrugClass());
        lqw.eq(StringUtils.isNotBlank(bo.getDrugInfoId()), DrugInventoryCheckPreparation::getDrugInfoId, bo.getDrugInfoId());
        lqw.eq(StringUtils.isNotBlank(bo.getStorageId()), DrugInventoryCheckPreparation::getStorageId, bo.getStorageId());
        lqw.eq(bo.getPackageNum() != null, DrugInventoryCheckPreparation::getPackageNum, bo.getPackageNum());
        lqw.eq(StringUtils.isNotBlank(bo.getPackageSpec()), DrugInventoryCheckPreparation::getPackageSpec, bo.getPackageSpec());
        lqw.eq(StringUtils.isNotBlank(bo.getPackageUnits()), DrugInventoryCheckPreparation::getPackageUnits, bo.getPackageUnits());
        lqw.eq(bo.getPurchasePrice() != null, DrugInventoryCheckPreparation::getPurchasePrice, bo.getPurchasePrice());
        lqw.eq(bo.getTradePrice() != null, DrugInventoryCheckPreparation::getTradePrice, bo.getTradePrice());
        lqw.eq(bo.getRetailPrice() != null, DrugInventoryCheckPreparation::getRetailPrice, bo.getRetailPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNo()), DrugInventoryCheckPreparation::getBatchNo, bo.getBatchNo());
        lqw.eq(bo.getExpireDate() != null, DrugInventoryCheckPreparation::getExpireDate, bo.getExpireDate());
        lqw.eq(bo.getAccountQuantity() != null, DrugInventoryCheckPreparation::getAccountQuantity, bo.getAccountQuantity());
        lqw.eq(bo.getActualQuantity() != null, DrugInventoryCheckPreparation::getActualQuantity, bo.getActualQuantity());
        lqw.eq(bo.getMaxQuantity() != null, DrugInventoryCheckPreparation::getMaxQuantity, bo.getMaxQuantity());
        lqw.eq(bo.getMinQuantity() != null, DrugInventoryCheckPreparation::getMinQuantity, bo.getMinQuantity());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), DrugInventoryCheckPreparation::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getSolidFill()), DrugInventoryCheckPreparation::getSolidFill, bo.getSolidFill());
        lqw.eq(StringUtils.isNotBlank(bo.getReserve2()), DrugInventoryCheckPreparation::getReserve2, bo.getReserve2());
        lqw.eq(StringUtils.isNotBlank(bo.getReserve3()), DrugInventoryCheckPreparation::getReserve3, bo.getReserve3());
        lqw.eq(StringUtils.isNotBlank(bo.getReserve4()), DrugInventoryCheckPreparation::getReserve4, bo.getReserve4());
        lqw.eq(StringUtils.isNotBlank(bo.getMinUnits()), DrugInventoryCheckPreparation::getMinUnits, bo.getMinUnits());
        lqw.eq(StringUtils.isNotBlank(bo.getMinSpec()), DrugInventoryCheckPreparation::getMinSpec, bo.getMinSpec());
        lqw.eq(bo.getAccountMoney() != null, DrugInventoryCheckPreparation::getAccountMoney, bo.getAccountMoney());
        lqw.eq(bo.getActualMoney() != null, DrugInventoryCheckPreparation::getActualMoney, bo.getActualMoney());
        lqw.eq(bo.getAccountMoneySales() != null, DrugInventoryCheckPreparation::getAccountMoneySales, bo.getAccountMoneySales());
        lqw.eq(bo.getActualMoneySales() != null, DrugInventoryCheckPreparation::getActualMoneySales, bo.getActualMoneySales());
        lqw.eq(bo.getProfitMoneySales() != null, DrugInventoryCheckPreparation::getProfitMoneySales, bo.getProfitMoneySales());
        return lqw;
    }

    /**
     * 新增药品预盘点表
     */
    @Override
    @GlobalTransactional
    public Boolean insertByBo(DrugInventoryCheckPreparationBo bo) {
        DrugInventoryCheckPreparation add = BeanUtil.toBean(bo, DrugInventoryCheckPreparation.class);
        List<DrugInventoryCheckPreparationBo> boList = bo.getDrugInventoryCheckPreparationBoList();
        String drugInventoryNo = remoteSerialNumberUtils.generateDrugInventoryNo(bo.getOrgId());
        Date checkYearMonthEnd = DateUtils.getNowDate();
        boList.forEach(itemBo -> {
            itemBo.setInventoryNo(drugInventoryNo);
            itemBo.setCheckYearMonth(DateUtils.dataFormat(DateUtils.YYYY_MM_DD, bo.getCheckYearMonth()));
            itemBo.setSaveType("0");
            itemBo.setPurchasePrice(itemBo.getTradePrice());
            itemBo.setOrgId(bo.getOrgId());
            itemBo.setDelFlag("0");
            itemBo.setSolidFill(UserConstants.YES);
            itemBo.setCheckYearMonthEnd(checkYearMonthEnd);
        });
        return baseMapper.insertBatch(BeanUtil.copyToList(boList, DrugInventoryCheckPreparation.class));
    }

    /**
     * 修改药品预盘点表
     */
    @Override
    public Boolean updateByBo(DrugInventoryCheckPreparationBo bo) {
        List<DrugInventoryCheckPreparationBo> boList = bo.getDrugInventoryCheckPreparationBoList();
        return baseMapper.insertOrUpdateBatch(BeanUtil.copyToList(boList, DrugInventoryCheckPreparation.class));
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DrugInventoryCheckPreparation entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除药品预盘点表
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 通过盘点号删除
     *
     * @param inventoryNo
     * @return
     */
    @Override
    public Boolean deleteWithValidByInventoryNo(String inventoryNo, String orgId) {
        return baseMapper.delete(Wrappers.<DrugInventoryCheckPreparation>lambdaUpdate()
                .eq(DrugInventoryCheckPreparation::getInventoryNo, inventoryNo)
                .eq(DrugInventoryCheckPreparation::getOrgId, orgId)
        ) > 0;
    }


    /**
     * 按申请单分组查询盘点记录
     *
     * @param bo
     * @return
     */
    @Override
    public TableDataInfo<DrugInventoryCheckPreparationVo> selectGroupInventoryNo(DrugInventoryCheckPreparationBo bo, PageQuery pageQuery) {
        Page<DrugInventoryCheckPreparationVo> result = baseMapper.selectGroupInventoryNo(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 获取盘点药品明细（通过批号等字段分组）
     *
     * @param bo
     * @return
     */
    @Override
    public List<DrugInventoryCheckPreparationVo> getInventoryCheckList(DrugInventoryCheckPreparationBo bo) {
        List<DrugInventoryCheckPreparationVo> drugInventoryCheckPreparationVoList = new ArrayList<>();
        if (bo.getCheckYearMonth() != null) {
            bo.setCheckYearMonth(DateUtils.dataFormat(DateUtils.YYYY_MM_DD, bo.getCheckYearMonth()));
        }
        drugInventoryCheckPreparationVoList = baseMapper.selectVoList(Wrappers.<DrugInventoryCheckPreparation>lambdaQuery()
                .eq(DrugInventoryCheckPreparation::getOrgId, bo.getOrgId())
                .eq(DrugInventoryCheckPreparation::getStorageId, bo.getStorageId())
                .eq(DrugInventoryCheckPreparation::getCheckYearMonth, bo.getCheckYearMonth())
                .orderByAsc(DrugInventoryCheckPreparation::getItemNo)
        );
        if (CollectionUtil.isEmpty(drugInventoryCheckPreparationVoList)) {
            DrugStockBo drugStockBo = new DrugStockBo();
            drugStockBo.setOrgId(bo.getOrgId());
            drugStockBo.setStorageId(bo.getStorageId());
            drugInventoryCheckPreparationVoList = baseMapper.getInventoryCheckList(drugStockBo);
            int i = 1;
            for (DrugInventoryCheckPreparationVo drugInventoryCheckPreparationVo : drugInventoryCheckPreparationVoList) {
//                drugInventoryCheckPreparationVo.setSaveType("0");
                drugInventoryCheckPreparationVo.setItemNo(i++);
            }

        } else {
            drugInventoryCheckPreparationVoList.forEach(drugInventoryCheckPreparationVo -> {
                drugInventoryCheckPreparationVo.setPackageUnitName(CollectionUtil.isNotEmpty(SPEC_UNIT_MAP)
                        && StringUtils.isNotBlank(drugInventoryCheckPreparationVo.getPackageUnits()) ?
                        SPEC_UNIT_MAP.stream()
                                .filter(i -> StringUtils.equals(drugInventoryCheckPreparationVo.getPackageUnits(), i.getDictValue()))
                                .findAny().get().getDictLabel() : "");
            });
        }
        return drugInventoryCheckPreparationVoList;
    }
}
